﻿//
//  Copyright (c) 2011 Extreme: Paweł Huryn (lead), Jakub Domański
//

using System;
using System.Collections.Generic;
using System.Linq;
using Extreme.SPFramework.Cache;

namespace Extreme.SPFramework.DomainModel
{
    /// <summary>
    /// Repository base with cache. Use only for small dictionary collections!
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class SharepointRepositoryBaseWithCache<T> : SharepointRepositoryBase<T>
        where T : EntityBase, new()
    {
        private string allItemsDictionaryKey = "5165024D-DEE2-4358-A9EE-825D00E8B6DF" + typeof(T).FullName;
        private readonly ICache cache;

        /// <summary>
        /// All items by id dictionary. Dictionary is instance-scope, but items reference to items in cache - do not modify them!
        /// </summary>
        protected Dictionary<int, T> AllItemsByIdDictionary { get; private set; }
        
        /// <summary>
        /// All items by unique id dictionary. Dictionary is instance-scope, but items reference to items in cache - do not modify them!
        /// </summary>
        protected Dictionary<Guid, T> AllItemsByUniqueIdDictionary { get; private set; }

        public SharepointRepositoryBaseWithCache(ICache cache)
        {
            this.cache = cache;
            LoadAllItemsDictionaries();
        }

        public override List<T> GetAllItems()
        {
            return AllItemsByIdDictionary.Values.ToList();
        }

        public override T GetItem(int id)
        {
            if(!AllItemsByIdDictionary.ContainsKey(id))
                RefreshCachedDictionary();

            if (AllItemsByIdDictionary.ContainsKey(id))
                return AllItemsByIdDictionary[id];
            else
                throw new Exception(String.Format("Item with id {0} of type {1} not found", id, typeof(T).Name));
        }

        public override T GetItem(Guid id)
        {
            throw new NotSupportedException("Get by Guid is not supported");
        }

        /// <summary>
        /// Gets all items by unique id dictionary
        /// </summary>
        public override Dictionary<Guid, T> GetAllItemsByUniqueIdDictionary()
        {
            return AllItemsByUniqueIdDictionary;
        }

        /// <summary>
        /// Gets all items by d dictionary
        /// </summary>
        public override Dictionary<int, T> GetAllItemsByIdDictionary()
        {
            return AllItemsByIdDictionary;
        }

        protected void LoadAllItemsDictionaries()
        {
            var cacheValue = cache.Get(allItemsDictionaryKey);
            if (cacheValue != cache.Empty)
            {
                // to make cache dictionary 'read-only':
                //AllItemsDictionary = new Dictionary<int, T>((Dictionary<int, T>)cacheValue);
                AllItemsByIdDictionary = (Dictionary<int, T>)cacheValue;
            }
            else
            {
                AllItemsByIdDictionary = base.GetAllItems().ToDictionary(item => item.ListId.Value);
                // to make cache dictionary 'read-only':
                //cache.Save(allItemsDictionaryKey, new Dictionary<int, T>(AllItemsDictionary));
                var configuration = base.GetMapippingConfiguration();
                cache.Save(allItemsDictionaryKey, AllItemsByIdDictionary, configuration.GetDefaultCacheTimespan());
            }

            AllItemsByUniqueIdDictionary =
                AllItemsByIdDictionary.Values.ToList().ToDictionary(item => item.UniqueId.Value);
        }

        private void RefreshCachedDictionary()
        {
            AllItemsByIdDictionary = null;
            cache.Clear(allItemsDictionaryKey);
            LoadAllItemsDictionaries();
        }
    }
}
